package com.interceptor;

import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import com.check.LoginCheck;
import com.example.demo.auth.constant.SessionConstants;
import com.example.demo.auth.constant.WFConstants;
import com.example.demo.auth.service.AuthCheck;
import com.example.demo.context.UserContext;
import com.example.demo.domain.vo.LogonUser;
import com.example.demo.domain.vo.UserInfoHN;
import com.exception.PermissionException;
import com.listener.PropertiesListenerConfig;
import com.utils.CookieUtils;
import com.utils.SecurityUtils;
import com.utils.StringUtils;



public class HnybSecurityInterceptor implements HandlerInterceptor {
	private final static Logger loger = LoggerFactory.getLogger(HnybSecurityInterceptor.class);
	public Boolean getBoolean(String key) {
        String value = key;
        if (value == null) {
            return false;
        }
        return Boolean.valueOf(value);
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    	if(request.getRequestURI().indexOf("/login") != -1) {
    		return true;
    	}else if(true){
    		return true;
    	}
    	HandlerMethod method = (HandlerMethod) handler;
        HttpSession session = request.getSession();

        /*
         *	登录信息的获取：先从session，再从缓存中
         *	缓存中的KEY，从cookie中读取userkey
         */
        LogonUser logonUser = null;
        
        //判断下参数中是否传入的可以判定用户的内容
        /*取消从请求和头中获取userkey,这样存在安全问题
         
        String userKey = request.getParameter(SecurityConstants.USER_KEY);

        if (StringUtils.isBlank(userKey)) {
            //从请求头中取
            userKey = request.getHeader(SecurityConstants.USER_KEY);
        }
        */
        //从会话中获取用户信息
        logonUser = (LogonUser) session.getAttribute(SessionConstants.USER);
        if(logonUser==null){
        	//会话中不存在用户信息，从cookie中取userkey,从缓存中获取
        	String userKey = CookieUtils.getCookieValueByName(request, WFConstants.USER_KEY);
            if (StringUtils.isNotBlank(userKey)) {
                logonUser = SecurityUtils.getLogonUser(userKey);
                if(logonUser!=null){
                	//用缓存中获取用户信息初始化到session中
                	session.setAttribute(SessionConstants.USER, logonUser);
                }
                
            } 
            
        }
        

        if (logonUser != null) {
            // 判断权限
        	
            AuthCheck authCheck = method.getMethodAnnotation(AuthCheck.class);
            if (authCheck == null || authCheck.value()) {
            	String url = request.getServletPath();

                //如果传入了菜单ID，通过菜单和url结合校验
                //对于菜单下面的操作没有经过权限控制的，可以继承父菜单权限
                String menuId = request.getParameter(WFConstants.MENU_KEY);
                boolean isAuthed = false;
                String debug = PropertiesListenerConfig.getProperty("sys.security.debug");
                System.out.println(getBoolean(debug));
            	if(getBoolean(debug)){
            		//如果调试权限时，不进行权限认证
            		isAuthed = true;
            	}else{
            		int lastpos = url.lastIndexOf("/");
                    String authUrl = null;//用于进行权限比对的URL
                    if(lastpos>1){
                    	//有子目录，保留子目录后+index,即把最后目录后的路径替换成index,
                    	authUrl = url.substring(0, lastpos).concat("/index");
                    }else{
                    	authUrl = url;
                    }
                    //add by fred 修当前用户数据进行权限认证
                    //按角色进行认证
                    if(authCheck!=null && StringUtils.isNotBlank(authCheck.role())){
                    	isAuthed = authRoleId(authCheck.role(),((UserInfoHN)logonUser.getExtInfo()).getRoleIdSet());
                    }else{
                    	//按URL进行认证
                    	isAuthed = authUrl(authUrl,((UserInfoHN)logonUser.getExtInfo()).getUrlSet());
                    }
                    /*
                    if (StringUtils.isNotBlank(menuId)) {
                        isAuthed = SecurityUtils.authUrl(logonUser, menuId, authUrl);
                    } else {
                        isAuthed = SecurityUtils.authUrl(logonUser, authUrl);
                    }*/
                    /* 取消 
                    if (!isAuthed) {
                        //如果url无法匹配，尝试匹配下原始规则（用于RESTFul）
                        String urlPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
                        if (urlPattern != null && !urlPattern.equals(url)) {
                            isAuthed = SecurityUtils.authUrl(logonUser, urlPattern);
                        }
                    }*/
            	}
                
                

                if (!isAuthed) {
                    throw new PermissionException("您未开通引能操作权限");
                }

            }

            // 修改上下文中的用户信息
            UserContext userContext = SecurityUtils.initUserContext(logonUser);
            userContext.put("aaa027", ((UserInfoHN)logonUser.getExtInfo()).getAaa027());
            userContext.put("dstype", "ds_");
            userContext.put("dscode", ((UserInfoHN)logonUser.getExtInfo()).getAaa027());
            userContext.put("code", ((UserInfoHN)logonUser.getExtInfo()).getCode());
            userContext.put("portalUserId", ((UserInfoHN)logonUser.getExtInfo()).getPortalUserId());
            userContext.put("portalUnitId", ((UserInfoHN)logonUser.getExtInfo()).getPortalUnitId());
            //刷新下Cookie
            CookieUtils.addCookie(response, WFConstants.USER_KEY, logonUser.getUserKey(), logonUser.getExpire());
        } else {
            // 未登录，根据是否需要校验抛出异常
            CookieUtils.removeCookie(response, WFConstants.USER_KEY);
            session.removeAttribute(SessionConstants.USER);
            
            LoginCheck logincheck = method.getMethodAnnotation(LoginCheck.class);
            if (logincheck == null || logincheck.value()) {
            	//String requrl = request.getServletPath();
            	//session.setAttribute("requrl", requrl);
                //throw new LoginException("此功能需登录后才可使用");
            	String requrl =  request.getServletPath()+(StringUtils.isBlank(request.getQueryString())?"":"?"+request.getQueryString());
            	String viewName = "/login?requrl="+requrl;
            	response.sendRedirect(viewName);
            }
        }
        return true;
    }
    /**
     *	认证用户是否有此角色
     * @param verRoleId 要认证的角色
     * @param userRoleIds 用哀悼拥有的角色
     * @return
     */
    private boolean authRoleId(String verRoleId,Set<String> userRoleIds){
    	if(StringUtils.isEmpty(verRoleId)&&userRoleIds!=null){
    		return userRoleIds.contains(verRoleId);
    	}
    	return false;
    }
    /**
     * 认证用户是否有此URL
     * @param verUrl 要认证的URL
     * @param userUrls 用户拥有的URL
     * @return
     */
    private boolean authUrl(String verUrl ,Set<String> userUrls){
    	if(StringUtils.isEmpty(verUrl) && userUrls!=null){
    		return userUrls.contains(verUrl);
    	}
    	return false;
    }
}

